package com.example.company_project_fangyu.demo.utils;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * HttpClient工具类
 */
@Component
public class HttpClientUtils {

    private static final Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);

    // 连接池管理器
    private PoolingHttpClientConnectionManager connectionManager;

    // HttpClient对象
    private CloseableHttpClient httpClient;

    // 请求配置
    private RequestConfig requestConfig;

    // 最大连接数
    private static final int MAX_TOTAL = 200;

    // 每个路由基础的连接数
    private static final int DEFAULT_MAX_PER_ROUTE = 100;

    // 连接超时时间(毫秒)
    private static final int CONNECT_TIMEOUT = 5000;

    // 请求超时时间(毫秒)
    private static final int CONNECTION_REQUEST_TIMEOUT = 5000;

    // 读取超时时间(毫秒)
    private static final int SOCKET_TIMEOUT = 5000;

    /**
     * 初始化方法
     */
    @PostConstruct
    public void init() {
        // 初始化连接池
        connectionManager = new PoolingHttpClientConnectionManager();
        // 最大连接数
        connectionManager.setMaxTotal(MAX_TOTAL);
        // 每个路由基础的连接数
        connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);

        // 设置请求配置
        requestConfig = RequestConfig.custom()
                .setConnectTimeout(CONNECT_TIMEOUT)
                .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
                .setSocketTimeout(SOCKET_TIMEOUT)
                .build();

        // 创建HttpClient
        httpClient = HttpClients.custom()
                .setConnectionManager(connectionManager)
                .setDefaultRequestConfig(requestConfig)
                .build();
    }

    /**
     * 销毁方法
     */
    @PreDestroy
    public void destroy() {
        if (connectionManager != null) {
            connectionManager.close();
        }
        if (httpClient != null) {
            try {
                httpClient.close();
            } catch (IOException e) {
                logger.error("关闭HttpClient失败", e);
            }
        }
    }

    /**
     * GET请求
     * @param url 请求地址
     * @return 响应结果
     */
    public String doGet(String url) {
        return doGet(url, null, null);
    }

    /**
     * GET请求
     * @param url 请求地址
     * @param params 请求参数
     * @return 响应结果
     */
    public String doGet(String url, Map<String, String> params) {
        return doGet(url, params, null);
    }

    /**
     * GET请求
     * @param url 请求地址
     * @param params 请求参数
     * @param headers 请求头
     * @return 响应结果
     */
    public String doGet(String url, Map<String, String> params, Map<String, String> headers) {
        // 构建带参数的URL
        String actualUrl = buildUrlWithParams(url, params);
        HttpGet httpGet = new HttpGet(actualUrl);

        // 设置请求头
        setHeaders(httpGet, headers);

        return executeRequest(httpGet);
    }

    /**
     * POST请求(表单提交)
     * @param url 请求地址
     * @param params 表单参数
     * @return 响应结果
     */
    public  String doPost(String url, Map<String, String> params) {
        return doPost(url, params, null);
    }

    /**
     * POST请求(表单提交)
     * @param url 请求地址
     * @param params 表单参数
     * @param headers 请求头
     * @return 响应结果
     */
    public String doPost(String url, Map<String, String> params, Map<String, String> headers) {
        HttpPost httpPost = new HttpPost(url);

        // 设置请求头
        setHeaders(httpPost, headers);

        // 构建表单参数
        if (params != null && !params.isEmpty()) {
            List<NameValuePair> paramList = new ArrayList<>();
            for (Map.Entry<String, String> entry : params.entrySet()) {
                paramList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            httpPost.setEntity(new UrlEncodedFormEntity(paramList, StandardCharsets.UTF_8));
        }

        return executeRequest(httpPost);
    }

    /**
     * POST请求(JSON格式)
     * @param url 请求地址
     * @param json JSON字符串
     * @return 响应结果
     */
    public String doPostJson(String url, String json) {
        return doPostJson(url, json, null);
    }

    /**
     * POST请求(JSON格式)
     * @param url 请求地址
     * @param json JSON字符串
     * @param headers 请求头
     * @return 响应结果
     */
    public String doPostJson(String url, String json, Map<String, String> headers) {
        HttpPost httpPost = new HttpPost(url);

        // 设置请求头
        setHeaders(httpPost, headers);

        // 设置JSON数据
        if (json != null) {
            StringEntity stringEntity = new StringEntity(json, StandardCharsets.UTF_8);
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);
        }

        return executeRequest(httpPost);
    }

    /**
     * PUT请求(JSON格式)
     * @param url 请求地址
     * @param json JSON字符串
     * @return 响应结果
     */
    public String doPutJson(String url, String json) {
        return doPutJson(url, json, null);
    }

    /**
     * PUT请求(JSON格式)
     * @param url 请求地址
     * @param json JSON字符串
     * @param headers 请求头
     * @return 响应结果
     */
    public String doPutJson(String url, String json, Map<String, String> headers) {
        HttpPut httpPut = new HttpPut(url);

        // 设置请求头
        setHeaders(httpPut, headers);

        // 设置JSON数据
        if (json != null) {
            StringEntity stringEntity = new StringEntity(json, StandardCharsets.UTF_8);
            stringEntity.setContentType("application/json");
            httpPut.setEntity(stringEntity);
        }

        return executeRequest(httpPut);
    }

    /**
     * DELETE请求
     * @param url 请求地址
     * @return 响应结果
     */
    public String doDelete(String url) {
        return doDelete(url, null);
    }

    /**
     * DELETE请求
     * @param url 请求地址
     * @param headers 请求头
     * @return 响应结果
     */
    public String doDelete(String url, Map<String, String> headers) {
        HttpDelete httpDelete = new HttpDelete(url);

        // 设置请求头
        setHeaders(httpDelete, headers);

        return executeRequest(httpDelete);
    }

    /**
     * 执行HTTP请求
     * @param request 请求对象
     * @return 响应结果
     */
    private String executeRequest(HttpRequestBase request) {
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(request);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                return EntityUtils.toString(entity, StandardCharsets.UTF_8);
            }
        } catch (IOException e) {
            logger.error("执行HTTP请求失败", e);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    logger.error("关闭HTTP响应失败", e);
                }
            }
            // 释放连接
            request.releaseConnection();
        }
        return null;
    }

    /**
     * 构建带参数的URL
     * @param url 原始URL
     * @param params 参数Map
     * @return 带参数的URL
     */
    private String buildUrlWithParams(String url, Map<String, String> params) {
        if (params == null || params.isEmpty()) {
            return url;
        }

        StringBuilder sb = new StringBuilder(url);
        if (url.indexOf('?') == -1) {
            sb.append('?');
        } else {
            sb.append('&');
        }

        boolean first = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (first) {
                first = false;
            } else {
                sb.append('&');
            }
            sb.append(entry.getKey()).append('=').append(entry.getValue());
        }

        return sb.toString();
    }

    /**
     * 设置请求头
     * @param request 请求对象
     * @param headers 请求头Map
     */
    private void setHeaders(HttpRequestBase request, Map<String, String> headers) {
        if (headers != null && !headers.isEmpty()) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                request.setHeader(entry.getKey(), entry.getValue());
            }
        }
    }
}